#import "ALTimelineViewController.h"
#import "NSObject+BlockObservation.h"
#import "NSManagedObjectContext+SMRAdditions.h"
#import "ALModelHeaders.h"
#import "ALTimelineTextEntryElement.h"
#import "NSManagedObject+SMRAdditions.h"
#import "ALTimelineRatingEntryElement.h"
#import "ALTimelineCanvas.h"


@interface ALTimelineEntryPreviewItem : NSObject <QLPreviewItem> {
}

@property (nonatomic, copy) NSURL *URL;
@property (nonatomic, retain) ALTimelineElement *timelineElement;
@property (readonly) NSURL *previewItemURL;
@property (readonly) NSString *previewItemTitle;

-(id)initWithElement:(ALTimelineElement *)theElement withURL:(NSURL *)theURL;

@end

@implementation ALTimelineEntryPreviewItem

@synthesize URL;
@synthesize timelineElement;

-(id)initWithElement:(ALTimelineElement *)theElement withURL:(NSURL *)theURL {
	if (!(self = [super init]))
		return nil;
	[self setURL:theURL];
	[self setTimelineElement:theElement];
	return self;
}

-(NSURL *)previewItemURL {
	return [self URL];
}

-(NSString *)previewItemTitle {
	return [[[self timelineElement] representedObject] label];
}

@end


#pragma mark -
@interface ALTimelineViewController ()
@property (nonatomic, retain) NSArray *quickLookPreviewItems;
@end


#pragma mark -
@interface ALTimelineViewController (ALTimelineViewControllerPrivateMethods)
//-(void)updateEntryFilter;
-(void)updatePreviewItems_;
@end


#pragma mark -
@implementation ALTimelineViewController

@synthesize entriesArrayController;
@synthesize timeline;
@synthesize textPrototype;
@synthesize quickLookPreviewItems;


-(void)awakeFromNib {
//	[self updateEntryFilter];
//	AMBlockTask selectorTask = ^(id object, NSDictionary *change) {
//		[self updateEntryFilter];
//	};
//	NSString *selectorKeyPath = [NSString stringWithFormat:@"values.%@", ALTemplateFiltersKey];
//	[[NSUserDefaultsController sharedUserDefaultsController] addObserverForKeyPath:selectorKeyPath task:selectorTask];
	
//	AMBlockTask arrangedObjectsTask = ^(id object, NSDictionary *change) {
//		LogDebug(@"New entries: %@", [[[self entriesController] arrangedObjects] valueForKey:ALLabelKey]);
//	};
//	[[self entriesController] addObserverForKeyPath:ALArrangedObjectsKey task:arrangedObjectsTask];
	[[self timeline] bind:ALTimelineContentBinding toObject:[self entriesArrayController] withKeyPath:ALArrangedObjectsKey options:nil];
//    NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
//    [noteCenter addObserver:self selector:@selector(filterScopeBarSelectionDidChange:) name:SMRScopeBarSelectionDidChangeNotification object:nil];
//    [noteCenter addObserver:self selector:@selector(customFilterSelectionDidChange:) name:ALCustomEntryFilterDidChangeNotification object:nil];
}

//-(void)updateEntryFilter {
//	NSArray *cachedURIStrings = [[NSUserDefaults standardUserDefaults] objectForKey:ALTemplateFiltersKey];
//	NSArray *cachedSelectedObjects = [[self managedObjectContext] smrObjectsWithURIStrings:cachedURIStrings];
//	NSMutableArray *cachedSelectedObjects = [NSMutableArray arrayWithCapacity:[cachedURIStrings count]];
//	for (NSString *uriString in cachedURIStrings) {
//		NSURL *uri = [NSURL URLWithString:uriString];
//		[cachedSelectedObjects addObject:[[self managedObjectContext] smrObjectWithURI:uri]];
//	}
//	
//	NSPredicate *filter = [NSPredicate predicateWithFormat:@"template IN %@", cachedSelectedObjects];
//	[[self entriesController] setFilterPredicate:filter];
//}


#pragma mark -
#pragma mark Notifications

-(void)filterScopeBarSelectionDidChange:(NSNotification *)note {
        // TODO: RE-CODE USING TAGS VICE sectionS
//    SMRScopeBarGroup *changedGroup = [note object];
//    if ([[changedGroup selectionIndexes] count] == 0)  // Group deselected
//        return;
//    NSString *groupIdentifier = [changedGroup identifier];
//    if ([groupIdentifier isEqualToString:kALDetailToolbarCustomGroupIdentifier])
//        return;
//    if ([groupIdentifier isEqualToString:kALDetailToolbarAllGroupIdentifier]) {
//        [[self entriesController] setFilterPredicate:nil];
//        return;
//    }
//    if (![groupIdentifier isEqualToString:kALDetailToolbarTagGroupIdentifier]) 
//        return;
//    ALsection *selectedsectionTemplate = [changedGroup selectedObject];
//    [[self entriesController] setFilterPredicate:[NSPredicate predicateWithFormat:@"template.sectionTemplate == %@", selectedsectionTemplate]];
}

-(void)customFilterSelectionDidChange:(NSNotification *)note {
    NSArray *selectedEntryTemplates = [note object];
    [[self entriesArrayController] setFilterPredicate:[NSPredicate predicateWithFormat:@"template IN %@", selectedEntryTemplates]];
}


#pragma mark -
#pragma mark Timeline delegate

-(NSDate *)timeline:(ALTimelineView *)aTimeline dateForRepresentedObject:(id)object {
	NSAssert([object isKindOfClass:[ALEntry class]], @"Expected object of class ALEntry, but class is %@", [object className]);
	return [(ALEntry *)object date];
}

-(ALTimelineElement *)timeline:(ALTimelineView *)aTimeline elementForRepresentedObject:(id)object {
	NSAssert([object isKindOfClass:[ALEntry class]], @"Expected object of class ALEntry rather than %@", [object className]);
	ALEntry *entry = (ALEntry *)object;
	ALElementType type = (ALElementType)[[[entry primaryElement] elementType] integerValue];
	ALTimelineElement *element = nil;
	switch (type) {
		case ALElementTypeText:
			element = [[ALTimelineTextEntryElement alloc] initWithNibName:@"TimelineTextElement" bundle:[NSBundle mainBundle]];
			break;
        case ALElementTypeRating:
            element = [[ALTimelineRatingEntryElement alloc] initWithNibName:@"TimelineRatingElement" bundle:[NSBundle mainBundle]];
            break;
		default:
			break;
	}
	return element;
}

-(NSString *)timeline:(ALTimelineView *)aTimeline uniqueStringForRepresentedObject:(id)representedObject {
	NSURL *uri = [representedObject smrURIRepresentation];
	return [uri absoluteString];
}

-(NSView *)timeline:(ALTimelineView *)aTimeline willForwardHitTestAtPoint:(NSPoint)aPoint toSubview:(NSView *)subview inElement:(ALTimelineElement *)hitElement {
	NSView *valueView = [(ALTimelineEntryElement *)hitElement valueView];
	BOOL valueViewIsEditable = [valueView respondsToSelector:@selector(isEditable)] && [[valueView valueForKey:@"isEditable"] boolValue];
	if (subview == valueView &&  valueViewIsEditable)
		return subview;
	return nil;
}

-(BOOL)timeline:(ALTimelineView *)aTimeline doCommandBySelector:(SEL)aSelector {
	LogDebug(@"%@", NSStringFromSelector(aSelector));
	if (aSelector == @selector(insertNewline:)) {
		NSArray *selectedElements = [aTimeline selectedElements];
		if ([selectedElements count] == 0)
			NSBeep();
		else {
			ALTimelineElement *firstSelected = [selectedElements objectAtIndex:0];
			[aTimeline editElement:firstSelected atPoint:NSZeroPoint];
		}
		return YES;
	}
	return NO;
}

-(BOOL)timeline:(ALTimelineView *)aTimeline insertText:(id)aString {
	if (![aString isEqualToString:@" "])
		return NO;
	
	if ([[aTimeline selectedElements] count] == 0)
		NSBeep();
	else 
		[NSApp sendAction:@selector(toggleQuickLook:) to:nil from:self];
	return YES;
}


#pragma mark -
#pragma mark Quick Look Controller

-(BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
	return YES;
}

-(void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
	WriteCacheFilesForEntries([[self timeline] selectedObjects]);
	[self updatePreviewItems_];
	[panel setDataSource:self];
	[panel setDelegate:self];
}

-(void)endPreviewPanelControl:(QLPreviewPanel *)panel {
	ClearQuicklookCacheFiles();
}


#pragma mark -
#pragma mark Quick Look Datasource

-(NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
	return [[self quickLookPreviewItems] count];
}


-(id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
	return [[self quickLookPreviewItems] objectAtIndex:index];
}

-(void)updatePreviewItems_ {
	NSMutableArray *previewItemArray = [NSMutableArray array];
	NSArray *selectedElements = [[self timeline] selectedElements];
	for (ALTimelineElement *element in selectedElements) {
		ALEntry *entry = [element representedObject];
		NSMutableArray *urls = [NSMutableArray arrayWithObject:CacheURLForEntry(entry)];
		[urls addObjectsFromArray:AttachmentURLsForEntry(entry)];
		for (NSURL *url in urls) {
			ALTimelineEntryPreviewItem *previewItem = [[ALTimelineEntryPreviewItem alloc] initWithElement:element withURL:url];
			[previewItemArray addObject:previewItem];
		}
	}
	[self setQuickLookPreviewItems:previewItemArray];
}


#pragma mark -
#pragma mark Quick Look delegate

-(NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item {
	ALTimelineElement *element = [(ALTimelineEntryPreviewItem *)item timelineElement];
	NSRect elementRect = [element currentPosition];
	ALTimelineCanvas *canvas = [[self timeline] canvas];
	NSRect elementRectBase = [canvas convertRectToBase:elementRect];
	NSRect elementRectScreen = elementRectBase;
	elementRectScreen.origin = [[canvas window] convertBaseToScreen:elementRectBase.origin];
	return elementRectScreen;
}

@end
